package com.guigusuqi.activiti.service.impl;

import com.guigusuqi.activiti.dto.TbInsertEvection;
import com.guigusuqi.activiti.entity.TbEvection;
import com.guigusuqi.activiti.mapper.TbEvectionMapper;
import com.guigusuqi.activiti.mapper.converter.EvectionConvertMapper;
import com.guigusuqi.activiti.service.TbEvectionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guigusuqi.commonutils.exeception.BusinessException;
import com.guigusuqi.commonutils.utils.GetTokenByAuthorizationUtils;
import com.guigusuqi.user.entity.LoginUser;
import com.guigusuqi.user.entity.SysUser;
import com.guigusuqi.user.service.SysUserService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author suqi
 * @since 2023-06-15
 */
@Service
public class TbEvectionServiceImpl extends ServiceImpl<TbEvectionMapper, TbEvection> implements TbEvectionService
{
    @Resource
    private SysUserService sysUserService;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;

    @Resource
    private HistoryService historyService;

    @Transactional
    @Override
    public String createEvection(TbInsertEvection insertEvection)
    {
        String token = GetTokenByAuthorizationUtils.getToken();
        LoginUser loginUser = sysUserService.checkAndParseToken(token);
        String userId = loginUser.getUser().getUserId();

        TbEvection tbEvection = EvectionConvertMapper.FLOW_CONVERT_MAPPER.toInsertDTO(insertEvection);
        tbEvection.setUserId(userId);
        save(tbEvection);

        String flowKey = insertEvection.getFlowKey();
        String businessKey = flowKey+":"+tbEvection.getId();

        //  修改业务状态
        tbEvection.setState(1);
        updateById(tbEvection);

        //  启动流程
        //  为各个流程节点设置审批人
        HashMap<String, Object> hashMap = sysUserService.setVariables(userId);
        hashMap.put("evection", tbEvection);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(flowKey, businessKey, hashMap);

        //  获取该用户的流程，并完成创建申请审批
        List<Map<String, Object>> taskList = listEvectionByUserId();
        if (ObjectUtils.isNotEmpty(taskList)) {
            for (Map<String, Object> map : taskList) {
                if (userId.equals(map.get("assignee")) &&
                        processInstance.getProcessDefinitionId().equals(map.get("processDefinitionId"))) {
                    completeTask("同意", (String) map.get("taskId"), userId);
                }
            }
        }

        return processInstance.getProcessDefinitionId();
    }

    @Override
    public void completeTask(String remark, String taskId, String userId)
    {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        if (!task.getAssignee().equals(userId))
        {
            throw new BusinessException("不是该用户进行审批!");
        }
        //  任务对象  获取流程实例Id
        String processInstanceId = task.getProcessInstanceId();

        //  设置审批人的userId
        Authentication.setAuthenticatedUserId(userId);

        //  添加记录
        taskService.addComment(taskId, processInstanceId, remark);

        System.out.println("-----------完成任务操作 开始----------");
        System.out.println("任务Id=" + taskId);
        System.out.println("负责人id=" + userId);
        System.out.println("流程实例id=" + processInstanceId);
        //  完成办理
        taskService.complete(taskId);
        System.out.println("-----------完成任务操作 结束----------");
    }

    @Override
    public List<HistoricTaskInstance> listHistoryEvectionByUserId()
    {
        String token = GetTokenByAuthorizationUtils.getToken();
        SysUser user = sysUserService.checkAndParseToken(token).getUser();

        return historyService.createHistoricTaskInstanceQuery().
                taskAssignee(user.getUserId()).list();
    }

    @Override
    public List<Map<String, Object>> listEvectionByUserId() {
        String token = GetTokenByAuthorizationUtils.getToken();
        LoginUser loginUser = sysUserService.checkAndParseToken(token);
        TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(loginUser.getUser().getUserId());

        List<Task> list = taskQuery.orderByTaskCreateTime().desc().list();

        List<Map<String, Object>> listmap = new ArrayList<Map<String, Object>>();
        for (Task task : list) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("taskId", task.getId());
            map.put("taskName", task.getName());
            map.put("description", task.getDescription());
            map.put("priority", task.getPriority());
            map.put("owner", task.getOwner());
            map.put("assignee", task.getAssignee());
            map.put("delegationState", task.getDelegationState());
            map.put("processInstanceId", task.getProcessInstanceId());
            map.put("executionId", task.getExecutionId());
            map.put("processDefinitionId", task.getProcessDefinitionId());
            map.put("createTime", task.getCreateTime());
            map.put("taskDefinitionKey", task.getTaskDefinitionKey());
            map.put("dueDate", task.getDueDate());
            map.put("category", task.getCategory());
            map.put("parentTaskId", task.getParentTaskId());
            map.put("tenantId", task.getTenantId());

            SysUser userInfo = sysUserService.findOneUserByName(loginUser.getUser().getUserName());
            map.put("assigneeUser", userInfo.getUserName());
            listmap.add(map);
        }
        return listmap;
    }
}
